package com.enterprise.dao;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.QueryRunner;

import com.enterprise.conn.*;

import com.enterprise.conn.*;

import java.util.*;
import java.lang.reflect.*;
import java.sql.*;


public class DAO<T> {

	public Class<T> clazz;
	public DAO(){
	
		Type type=getClass().getGenericSuperclass();
	//	System.out.println(type);//获取继承该类带具体泛型的父类（此类） 或者获取此类的父类（Object)
		ParameterizedType parameterizedType=(ParameterizedType)type;
		Type[] ars=parameterizedType.getActualTypeArguments();//获取泛型参数数组
		clazz=(Class) ars[0];
	//	System.out.println(clazz);
	}
	/**
	 * 增，删，改操作
	 * @param sql
	 * @param args
	 * @return
	 */
	public  int executeUpdate(String sql,Object...args){
		Connection connection=JDBCUtils.getConnection();
		PreparedStatement preparedStatement=null;
		try {
			preparedStatement=connection.prepareStatement(sql);
			if(args!=null&&args.length>0){
				for(int i=0;i<args.length;i++){
					preparedStatement.setObject(i+1, args[i]);
				}
			}
			return preparedStatement.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return -1;
		}finally {
			JDBCUtils.releaseConnection(connection, preparedStatement, null);
		}
	}

	/**
	 * 查询
	 * @param clazz
	 * @param sql
	 * @param args
	 * @return
	 */
	@SuppressWarnings("finally")
	public  List<T> getForList(String sql, Object... args) {

		List<T> list = new ArrayList<>();

		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;

		try {
			//1. 得到结果集
			connection = JDBCUtils.getConnection();
			preparedStatement = connection.prepareStatement(sql);
			if(args!=null&&args.length>0){
				for (int i = 0; i < args.length; i++) {
					preparedStatement.setObject(i + 1, args[i]);
				}
			}

			resultSet = preparedStatement.executeQuery();
			
			//2处理结果解，得到Map的list，其中一个Map对象就是一条记录。
			//Map的key为resultSet中的列的别名，Map的value为列的值
			List<Map<String, Object>> values = 
					handleResultSetToMapList(resultSet);
			
			//3.把List<Map<String,Object>> 转化成Class对象(clazz)的实例集List<T>
			list = transfterMapListToBeanList( values);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.releaseConnection(connection,preparedStatement,resultSet);
			
		}
		return list;
	
	}
	
	
	public List<T> transfterMapListToBeanList(List<Map<String, Object>> values) throws InstantiationException,
			IllegalAccessException, InvocationTargetException {

		List<T> result = new ArrayList<>();

		T bean = null;

		if (values.size() > 0) {
			for (Map<String, Object> m : values) {
				bean = clazz.newInstance();
				for (Map.Entry<String, Object> entry : m.entrySet()) {
					String propertyName = entry.getKey();
					Object value = entry.getValue();
					//利用org.apache.commons.beanutils.BeanUtils工具类反射设置对象属性
					BeanUtils.setProperty(bean, propertyName, value);
					
				/*	try {
						ReflectorUtil.setProperty(bean, propertyName, value);
					} catch (NoSuchFieldException | SecurityException | IllegalArgumentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}*/
				}
				result.add(bean);
			}
		}

		return result;
	}
	
	
	public List<Map<String, Object>> handleResultSetToMapList(
			ResultSet resultSet) throws SQLException {
		
		List<Map<String, Object>> values = new ArrayList<>();
		//获取列名
		List<String> columnLabels = getColumnLabels(resultSet);
		Map<String, Object> map = null;
		while (resultSet.next()) {
			map = new HashMap<>();

			for (String columnLabel : columnLabels) {
				Object value = resultSet.getObject(columnLabel);
				map.put(columnLabel, value);
			}
			values.add(map);
		}
		return values;
	}
	
	private  List<String> getColumnLabels(ResultSet rs) throws SQLException {
		List<String> labels = new ArrayList<>();

		ResultSetMetaData rsmd = rs.getMetaData();
		for (int i = 0; i < rsmd.getColumnCount(); i++) {
			labels.add(rsmd.getColumnLabel(i + 1));
		}

		return labels;
	}
	public int getCount(String sql,String...id){
		Connection connection=null;
		ResultSet resultSet=null;
		PreparedStatement preparedStatement=null;
		try {
			 connection=JDBCUtils.getConnection();
			 resultSet=null;
			 preparedStatement=connection.prepareStatement(sql);
			if(id!=null&&id.length>0){
				for(int i=1;i<=id.length;i++)
				preparedStatement.setString(i, id[i-1]);
			}
			resultSet=preparedStatement.executeQuery();
			if(resultSet.next()){
				return resultSet.getInt(1);
			}
			else {
				return 0;
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 0;
		}finally{
			JDBCUtils.releaseConnection(connection, preparedStatement, resultSet);
		}
	}
	/**
	 * 返回单条查询记录
	 * @param sql
	 * @param args
	 * @return
	 */
	public <T> T get(String sql, Object... args) {
		List<T> result = (List<T>) getForList(sql, args);
		if(result.size() > 0){
			return result.get(0);
		}
		
		return null;
	}
	/**
	 * 得到结果集，只返回一行一列
	 * @param sql
	 * @param args
	 * @return
	 */
	public  <E> E getForValue(String sql, Object... args) {
		
		//1. 得到结果集，只有一行一列
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;

		try {
			
			connection = JDBCUtils.getConnection();
			preparedStatement = connection.prepareStatement(sql);

			for (int i = 0; i < args.length; i++) {
				preparedStatement.setObject(i + 1, args[i]);
			}

			resultSet = preparedStatement.executeQuery();
			
			if(resultSet.next()){
				return (E) resultSet.getObject(1);
			}
		} catch(Exception ex){
			ex.printStackTrace();
		} finally{
			JDBCUtils.releaseConnection(connection, preparedStatement, resultSet);
		}
	
		
		return null;
	}
	
	
}
